home *** CD-ROM | disk | FTP | other *** search
- Notes for DocObjects Framer (Container) Sample
- Kraig Brockschmidt, kraigb@microsoft.com
- November 1995
-
-
-
- Framer is intended to demonstrate simple OLE Document Objects hosting as
- a container. That is, Framer demonstrates the basic support necessary to
- host DocObjects. It is implemented according to the guidlines in the
- "Document Objects Specification" document and has been tested against
- Microsoft Word and Microsoft Excel as well as a few other OLE-enabled
- applications that do not support DocObjects.
-
-
- Framer itself has almost nothing in the way of its own user interface such
- as a more complete host would, such as the Office Binder. Framer has these
- menu commands available:
-
- Command Description
- ----------------------------------------------------------------------
- File Open Displays a File Open dialog and allows the user to select
- a file. Framer will attempt to activate a DocObject for
- the file. Failing that it will create a standard
- embedded object and activate it in a separate window.
- This command is disabled when an object already exists.
- File/Close must be used before creating another object.
-
- File Close Closes the DocObject that is currently open; if the object
- is just an embedding it will destroy that object which has
- the effect of closing the server as well. Try opening
- a .BMP file (which should activate PaintBrush, for instance)
- and use Close to see the effect.
-
- File Exit Performs File/Close if necessary and terminates Framer.
-
- Help About Displays Framer's About box. This command exists to
- demonstrate DocObject Help menu merging.
-
-
- Whenever Framer knows it has an object it displays a small message in its
- client area to remind you that you have to File/Close before creating another.
-
-
- Creating and Activating an Object
- ---------------------------------
- When you "Open" a file in Framer, the code call OleCreateFromFile to create
- an embedded object from the contents of the file. This has two possible
- results:
-
- 1. An embedded object with a real OLE server behind it.
- 2. A package object managed by Packager
-
- The next step Framer takes is to activate the object with IOleObject::DoVerb
- passing OLEIVERB_SHOW.
-
- If the object is a package object, then packager will launch the file or
- execute the command line in it as it should. This will generally display
- another window (like notepad for a TXT file) that is completely disconnected
- from Framer. Using File/Close in Framer will not affect this other window
- as that will only destroy the Package object itself. You'll have to
- manually close the other applications.
-
- If the object is a real embedded object, then one of two things will happen
- upon activation:
-
- 1. If the object doesn't know about DocObjects, it is activated in
- another window. Using File/Close in this case will close the server.
- Closing the server itself will cause Framer to do the equivalent
- of File/Close, which frees the object and re-enables File/Open.
- See CImpIIAdviseSink::OnClose in iadvsink.cpp. The closing
- sequence is in CFrame::Close in framer.cpp.
-
- 2. If the object is a DocObject, then it will start the DocObject
- activation sequence, primarily by calling IOleDocumentSite::ActivateMe
- which is found in idocsite.cpp. Inside this member, Framer
- then performs the standard sequence of document object activation
- steps. After these steps a DocObject will be fully interactive;
- using File/Close on the menu, which Framer still owns, will
- deactivate the object through CFrame::Close which performs the
- same set of steps as in #1 above.
-
-
-
- Help Menu Merging
- -----------------
-
- Framer implements the container side of the Help menu merging protocol
- described in the Document Object Specification. This involves the members
- CFrame::InsertMenus, CFrame::SetMenu, and CFrame::RemoveMenus. The
- InsertMenus method will install Framer's Help menu in the correct location
- on the shared menu. The container-side popup used here is loaded from
- Framer's resources on startup in CFrame::Init.
-
- Inside CFrame::SetMenu, Framer checks if there's more than one item on
- the menu added in InsertMenus. If so, then Framer remembers this fact
- for later message handling. Otherwise Framer removes this menu from the
- shared menu entirely as the DocObject itself isn't using this shared
- capability.
-
- Inside CFrame::RemoveMenus, Framer simply makes sure that its own Help
- menu is removed as it should be.
-
- The really interesting stuff happens in FrameWndProc (framer.cpp) in the
- WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT, and WM_COMMAND cases. Inside
- WM_INITMENU Framer clears a flag that indicates whether the last popup menu
- that was being used was the object's additions to the Help menu. Inside
- WM_MENUSELECT, Framer checks if the originating menu is a popup and if so,
- it checks if that popup is on the shared "Help" popup, and if that is also
- true then Framer checks if the item being used is the first one or some
- other one. The first item is what Framer knows to be its own Help item, so
- it just handles the messages as usual. Otherwise the user is working with
- a DocObject-owned menu, so Framer sets the flag m_fInObjectHelp variable
- to TRUE and forwards the message to the object's window (available from
- IOleInPlaceObject::GetWindow).
-
- As long as m_fInObjectHelp is set, Framer will forward WM_COMMAND,
- WM_INITMENUPOPUP, and WM_MENUSELECT messages. As soon as another
- WM_MENUSELECT message is seen for another non-object menu, then Framer
- will reset the flag and begin processing messages once again itself.
-
- In this way you'll see, with Microsoft Word for example, the correct
- behavior of a shared Help popup.
-
-
-
-
-
- Known Feature Limitations
- -------------------------
- 1. Framer does not print so it does not use the IPrint interface nor does
- it implement IContinueCallback.
-
- 2. Framer does nothing with command targets.
-
- 3. Framer does not forward owner-draw menu messages to the object which
- means that if owner-draw menus are used in a DocObject help menu,
- this sample will not work correctly.
-
- 4. Framer does not provide for actually saving any changes made to a
- DocObject. Because a DocObject is an embedding, Framer has to provide
- an instance of IStorage through IPersistStorage::InitNew or ::Load. It
- does this using a temporary Compound File that is deleted when Framer
- exits. Therefore any changes made to the data in the DocObject will
- simply be discarded.
-
-
- Potential for Better UI
- -----------------------
-
- The item #4 above takes a little more explanation. When OleCreateFromFile is
- used in the File/Open command, Framer is making a COPY of the file contents.
- When a DocObject is activated with this content, the DocObject has a copy
- of the file contents, not the contents of the file itself. Therefore any
- changes made there will not be reflected back into the original file, although
- Framer's UI suggests that this should happen.
-
- A real DocObject container like the Office Binder actually stores all the
- object data in its own Compound File, not as separate files. If one needs
- to have a DocObject save into a separate file, then the container needs to
- either use command-targets or has to call IPersistFile::Save to accomplish
- this step.
-
- In short, DocObjects is not about activating the apps that manipulate files;
- it's about activating embedded *documents* saved within the container file
- *as if* those documents were stand alone.
-
- Framer's UI, which is really inappropriate for DocObjects, exists as it does
- for simplicity's sake.
-
- A more appropraite container application would maintain its own "files" in
- which it collected data from a number of other "documents" which are stored
- simply as embedded objects. The Office Binder does exactly this, where
- a "Binder" is a Compound File with sub-storages for each "section" in the
- document.
-
- Certainly with some more work on UI, Framer could become such an application.
-